 #include "mainwidget.h"
#include "./ui_mainwidget.h"
#include "sessionfriendarea.h"
#include "debug.h"
#include <QVBoxLayout>
#include "selfinfowidget.h"
#include "sessiondetailwidget.h"
#include "groupsessiondetailwidget.h"
#include "addfrienddialog.h"
#include "model/datacenter.h"
#include "toast.h"

using namespace model;

MainWidget* MainWidget:: instance = nullptr;

MainWidget *MainWidget::getInStance()
{
    if (instance == nullptr)
    {
        //此处new不传入参数以桌面为父窗口
        //由于此处的窗口是整个程序的主窗口,父窗口就设定为桌面.
        instance = new MainWidget();
    }
    return instance;
}

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainWidget)
{
    //建立Qt Designer设计的界面的关联
    ui->setupUi(this);
    //this->setStyleSheet("QWidget{background:white;}");
    this->setWindowTitle("我的聊天室");
    this->setWindowIcon(QIcon(":/resource/image/logo.png"));

    //初始化主窗口样式布局
    initMainWindow();

    //初始化左窗口布局
    initLeftWindow();

    //初始化中间窗口布局
    initMidWindow();

    //初始化右窗口布局
    initRightWindow();

    //初始化信号槽
    initSignalSlot();

    //初始化websocket
    initWebSocket();
}

MainWidget::~MainWidget()
{
    delete ui;
}

void MainWidget::initMainWindow()
{
    QHBoxLayout *layout = new QHBoxLayout();

    //spacing 就是layout 内部元素之间的间隔距离,设为0就是紧挨着.
    layout->setSpacing(0);
    //layout里面元素距离四个边界的距离
    layout->setContentsMargins(0, 0, 0, 0);
    this->setLayout(layout);

    windowLeft  = new QWidget();
    windowMid =  new QWidget();
    windowRight = new  QWidget();

    windowLeft ->setFixedWidth(70);
    windowMid->setFixedWidth(260);
    //设置宽度自适应
    windowRight->setMinimumWidth(800);

    windowLeft->setStyleSheet("QWidget { background-color: rgb(46, 46, 46);}");
    windowMid->setStyleSheet("QWidget { background-color: rgb(243, 243, 243);}");
    windowRight->setStyleSheet("QWidget { background-color: rgb(244, 244, 255);}");

    layout->addWidget(windowLeft);
    layout->addWidget(windowMid);
    layout->addWidget(windowRight);
}

void MainWidget::initLeftWindow()
{
    QVBoxLayout* layout = new QVBoxLayout();
    windowLeft->setLayout(layout);

    //设置按钮间距
    layout->setSpacing(20);
    //左上右下
    layout->setContentsMargins(0, 50, 0, 0);

    //添加用户头像
    userAvatar = new QPushButton();
    userAvatar->setFixedSize(45, 45);
    userAvatar->setIconSize(QSize(30, 30));
    //把设置默认头像注释, 此时, 就可以避免出现,"头像的变化"
    //userAvatar->setIcon(QIcon(":/resource/image/defaultAvatar.png"));
    //将背景色设为透明,应用父元素的背景颜色
    userAvatar->setStyleSheet("QPushButton { background-color : transparent; }");

    //void QBoxLayout::addWidget(QWidget *widget, int stretch = 0, Qt::Alignment alignment = Qt::Alignment())
    //1 表示缩放比
    //Qt::AlignTop：表示将按钮对齐到布局的顶部。
    //Qt::AlignHCenter：表示将按钮在水平方向上居中对齐。
    layout->addWidget(userAvatar, 1, Qt::AlignTop | Qt::AlignHCenter);

    //添加会话标签
    sessionTabBtn = new QPushButton();
    sessionTabBtn->setFixedSize(45, 45);
    sessionTabBtn->setIconSize(QSize(30 ,30));
    sessionTabBtn->setIcon(QIcon(":/resource/image/session_active.png"));
    sessionTabBtn->setStyleSheet("QPushButton { background-color : transparent; }");
    layout->addWidget(sessionTabBtn, 1, Qt::AlignTop | Qt::AlignHCenter);

    //添加好友标签
    friendTabBtn = new QPushButton();
    friendTabBtn->setFixedSize(45, 45);
    friendTabBtn->setIconSize(QSize(30, 30));
    friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));
    friendTabBtn->setStyleSheet("QPushButton {background-color : transparent; }");
    layout->addWidget(friendTabBtn, 1, Qt::AlignTop | Qt::AlignHCenter);

    //添加好友申请标签
    applyTabBtn = new QPushButton();
    applyTabBtn->setFixedSize(45, 45);
    applyTabBtn->setIconSize(QSize(30, 30));
    applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));
    applyTabBtn->setStyleSheet("QPushButton { background-color: transparent; }");
    layout->addWidget(applyTabBtn, 1, Qt::AlignTop | Qt::AlignHCenter);
    // 下⽅添加空隙, 把上述控件挤上去,添加空隙
    layout->addStretch(20);
}

void MainWidget::initMidWindow()
{
    QGridLayout* layout = new QGridLayout();
    //距离上方20px的距离, 另外三个方向不要边框
    layout->setContentsMargins(0, 10, 0, 0);
    layout->setHorizontalSpacing(0);
    layout->setVerticalSpacing(10);
    windowMid->setLayout(layout);

    //设置搜索框
    searchEdit = new QLineEdit();
    searchEdit->setFixedHeight(25);
    searchEdit->setPlaceholderText("搜索");
    //padding-left: 5px;: 在输入框的左侧添加 5 像素的内边距，确保文本不会紧贴控件边缘
    //border-radius: 5px;: 设置输入框的圆角半径为 5 像素，使得控件的角看起来更加圆润。
    searchEdit->setStyleSheet("QLineEdit { border-radius: 5px; background-color : rgb(226, 226, 226); padding-left: 5px;}");

    //设置添加按钮
    addFriendBtn = new QPushButton();
    addFriendBtn->setFixedSize(25, 25);
    addFriendBtn->setIcon(QIcon(":/resource/image/cross.png"));
    QString style = "QPushButton { border-radius: 5px; background-color: rgb(226, 226, 226) ;} ";
    style += " QPushButton:pressed { background-color: rgb(240, 240, 240) ;}";
    addFriendBtn->setStyleSheet(style);
    sessionFriendArea  = new SessionFriendArea();

    //为了灵活控制边距,只影响搜索框第一行,不影响下方列表这一行
    //创建空白 widget 填充到布局管理器中
    QWidget* spacer1 = new QPushButton();
    QWidget* spacer2 = new QPushButton();
    QWidget* spacer3 = new QPushButton();
    spacer1->setFixedWidth(10);
    spacer1->setStyleSheet("border: none;");
    spacer2->setFixedWidth(10);
    spacer2->setStyleSheet("border: none;");
    spacer3->setFixedWidth(10);
    spacer3->setStyleSheet("border: none;");
    //行列跨度默认为1
    layout->addWidget(spacer1, 0, 0);
    layout->addWidget(searchEdit, 0, 1);
    layout->addWidget(spacer2, 0, 2);
    layout->addWidget(addFriendBtn, 0, 3);
    layout->addWidget(spacer3, 0, 4);

    // 1: 控件的行索引，表示 sessionFriendArea 将放置在网格的第 2 行（行索引从 0 开始）。
    // 0: 控件的列索引，表示 sessionFriendArea 将放置在网格的第 1 列。
    // 1: 控件的行跨度，表示 sessionFriendArea 在网格中占用 1 行。
    // 5: 控件的列跨度，表示 sessionFriendArea 在网格中占用 5 列。
    layout->addWidget(sessionFriendArea, 1, 0, 1, 5);

}

void MainWidget::initRightWindow()
{
    //1.创建右窗口布局管理器
    QVBoxLayout* vlayout = new QVBoxLayout();
    vlayout->setSpacing(0);
    vlayout->setContentsMargins(0, 0, 0, 0);
    vlayout->setAlignment(Qt::AlignTop);
    windowRight->setLayout(vlayout);

    //2.创建上方标题栏
    QWidget* titleWidget = new QWidget();
    titleWidget->setFixedHeight(45);
    titleWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    titleWidget->setObjectName("titleWidget");
    titleWidget->setStyleSheet("#titleWidget { border-bottom: 1px solid rgb(230, 230, 230); border-left: 1px solid rgb(230, 230, 230);}");
    vlayout->addWidget(titleWidget);

    //创建标题栏的水平布局管理器
    QHBoxLayout* hlayout = new QHBoxLayout();
    hlayout->setSpacing(0);
    //使标题的Label和按钮 距离左右两侧的边界,10边距
    hlayout->setContentsMargins(10, 0, 10, 0);
    titleWidget->setLayout(hlayout);
    //3.给标题栏,添加标题label和一个按钮
    sessionTitleLabel = new QLabel();
    sessionTitleLabel->setStyleSheet("QLabel {font-size: 22px; border-bottom : 1px solid rgb(230, 230, 230);}");
    hlayout->addWidget(sessionTitleLabel);
#if TEST_UI
    //为了测试临时增加的,实际内容应该从服务器获取数值来设置
    sessionTitleLabel->setText("这是会话标题");
#endif
    //标题栏的按钮...
    extraBtn = new QPushButton();
    extraBtn->setFixedSize(30, 30);
    extraBtn->setIconSize(QSize(30, 30));
    extraBtn->setIcon(QIcon(":/resource/image/more.png"));
    extraBtn->setStyleSheet("QPushButton { border:none; background-color: rgb(245, 245 ,245);"
                            "} QPushButton:pressed{ background-color: rgb(220, 220, 220);}");
    hlayout->addWidget(extraBtn);

    //4.添加消息展示区
    messageShowArea = new MessageShowArea();
    vlayout->addWidget(messageShowArea);

    //5.添加消息编辑区
    messageEditArea = new MessageEditArea();

    //确保消息区处于窗口下方
    vlayout->addWidget(messageEditArea, 0, Qt::AlignBottom);




}

void MainWidget::initSignalSlot()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();

    //////////////////////////////////////
    //连接信号槽,解决标签切换问题
    /////////////////////////////////////

    connect(sessionTabBtn, &QPushButton::clicked, this, &MainWidget::switchTabToSession);
    connect(friendTabBtn,  &QPushButton::clicked, this, &MainWidget::switchTabToFriend);
    connect(applyTabBtn,   &QPushButton::clicked, this, &MainWidget::switchTabToApply);

    //////////////////////////////////////
    //点击自己的头像,弹出对话框显示个人主页
    /////////////////////////////////////

    connect(userAvatar, &QPushButton::clicked, this, [=](){
        SelfInfoWidget* selfInfoWidget = new SelfInfoWidget(this);
        selfInfoWidget->exec();//弹出模态对话框
        //selfInfoWidget->show();//弹出非模态

    });

    ///////////////////////////////////
    //点击会话详情按钮弹出会话详情窗口
    ////////////////////////////////
    connect(extraBtn, &QPushButton::clicked, this, [=](){
        //判定当前会话是单聊还是群聊
        //这个bool变量根据当前选中的实际会话决定(后续接入服务器,获取真实数据之后)
// #if TEST_GROUP_SESSION_DETAIL
//         bool isSingleChat = false;
// #else
//          bool isSingleChat = true;
// #endif


        //获取到当前会话的详细信息,通过会话中的userId属性
        ChatSessionInfo* chatSessionInfo = dataCenter->findChatSessionById(dataCenter->getCurrentChatSessionId());
        if (chatSessionInfo == nullptr) {
            LOG() << "当前对话不存在无法弹出会话详情对话框";
            return;
        }
        bool isSingleChat = chatSessionInfo->userId !="";

        if(isSingleChat)
        {
        //单聊,弹出这个窗口
        UserInfo* userInfo = dataCenter->findFriendById(chatSessionInfo->userId);
        if (userInfo == nullptr) {
            //单聊会话对应的用户不存在
            LOG() << "单聊会话对应的用户不存在, 无法弹出会话详情窗口";
            return;
        }

        SessionDetailWidget* sessionDetailWidget = new SessionDetailWidget(this, *userInfo);
        sessionDetailWidget->exec();
        }
        else
        {
        //群聊,弹出另一个窗口
         GroupSessionDetailWidget* groupSessionDetailWidget = new GroupSessionDetailWidget(this);
        groupSessionDetailWidget->exec();
        }
    });

    ///////////////////////////////////
    //点击添加好友窗口,弹出添加好友窗口
    ////////////////////////////////
    connect(addFriendBtn, &QPushButton::clicked, this, [=](){
        AddFriendDialog* addFriendDialog = new AddFriendDialog(this);
        addFriendDialog->exec();

    });

    ///////////////////////////////////
    //修改搜索框内容弹出添加好友对话框
    ////////////////////////////////
    connect(searchEdit, &QLineEdit::textEdited, this, [=](){
    //textEdit 只有用户在输入框输入的时候,才会触发
    //textChanged, 用户在输入框输入会触发, 或者代码中修改setText也会触发;

    AddFriendDialog* addFriendDialog = new AddFriendDialog(this);
    // 取出输入框的内容,设置到新弹窗的输入框里面
    const QString& searchKey = searchEdit->text();
    addFriendDialog->setSearchKey(searchKey);
    //清空主窗口文本内容
    searchEdit->setText("");
    //放在exec()前面exec为阻塞接口
    addFriendDialog->exec();
    });

    ///////////////////////////////////
    //获取个人信息
    ////////////////////////////////

   //提供一个具体方法,来获取到网络数据
    connect(dataCenter, &DataCenter::getMyselfDone, this, [=](){
        //从DataCenter 中拿到响应的结果的myself, 把里面的头像取出来, 显示到界面上
        auto myself  = dataCenter->getMyself();
        userAvatar->setIcon(myself->avatar);
    });
    dataCenter->getMyselfAsync();

    ///////////////////////////////////
    //获取好友列表
    ////////////////////////////////

    loadFriendList();

    ///////////////////////////////////
    //获取会话列表
    ////////////////////////////////

    loadSessionList();

    ///////////////////////////////////
    //获取好友申请列表
    ////////////////////////////////
    loadApplyList();

    //////////////////////////////////
    /// 处理修改头像
    /// ////////////////////////////
    connect(dataCenter, &DataCenter::changeAvatarDone, this, [=](){
        UserInfo* myself = dataCenter->getMyself();
        userAvatar->setIcon(myself->avatar);
    });


    /////////////////////////////////
    /// 处理删除好友
    /// /////////////////////////
    connect(dataCenter, &DataCenter::deleteFriendDone, this, [=](){
        //更新会话列表和好友列表
        this->updateFriendList();
        this->updateChatSessionList();
        LOG() << "删除好友完成";
    });

    ///////////////////////////////
    /// 清除当前选中会话
    /// //////////////////////////
    connect(dataCenter, &DataCenter::clearCurrentSession, this, [=](){
       //清空当前会话标题
        sessionTitleLabel->setText("");
        messageShowArea->clear();
        dataCenter->setCurrentChatsessionId("");
        LOG() << "清空当前会话完成";
    });



    /////////////////////////////
    /// 处理添加好友申请
    //////////////////////////////
    connect(dataCenter, &DataCenter::addFriendApplyDone, this, [=](){
        Toast::showMessage("好友申请已发送");
    });


    ///////////////////////////////
    /// 处理添加好友申请的推送数据
    /// ///////////////////////////
    connect(dataCenter, &DataCenter::receiveFriendApplyDone, this, [=](){
        this->updateApplyList();
        Toast::showMessage("收到新的好友申请");
    });


    //////////////////////////
    /// 处理同意好友申请
    /// //////////////////
    connect(dataCenter, &DataCenter::acceptFriendApplyDone, this, [=](){
        this->updateApplyList();
        this->updateFriendList();
        Toast::showMessage("好友已经添加完成");

    });
    ///////////////////////
    /// 处理拒绝好友申请
    /// ////////////
    connect(dataCenter, &DataCenter::rejectFriendApplyDone, this, [=](){
        //需要更新新好友申请列表,刚才拒绝的这一项,是需要删除掉的
        this->updateApplyList();
        Toast::showMessage("好友申请已经拒绝");
    });

    /////////////////////////
    /// 处理好友申请结果的推送数据
    /// ///////////////
    connect(dataCenter, &DataCenter::receiveFriendProcessDone, this ,[=](const QString& nickname, bool argee){
        if (argee) {
            //同意
            this->updateFriendList();
            Toast::showMessage(nickname +"已经同意了你的好友申请");
        } else {
            //拒绝
            Toast::showMessage(nickname +"已经拒绝了你的好友申请");
        }
    });

    /////////////////////////
    ///处理创建群聊的响应信号
    /// ///////////////
    connect(dataCenter, &DataCenter::createGroupChatSessionDone, this, [=](){
        Toast::showMessage("创建群聊会话请求已经发送");
    });

    /////////////////////////
    ///处理创建会话的推送数据
    /// ///////////////
    connect(dataCenter, &DataCenter::receiveSessionCreateDone, this, [=](){
       //更新一下界面
        this->updateChatSessionList();
        //通知用户已经入群
        Toast::showMessage("您被拉入到新的群聊中");
    });



}

void MainWidget::initWebSocket()
{
    DataCenter* dataCenter =  DataCenter::getInstance();
    dataCenter->initWebsocket();
}

void MainWidget::switchTabToSession()
{
  //1.记录当前切换到了哪个标签页
    activetab = SESSION_LIST;
  //2.调整图标情况,把会话的按钮图标设为 active,另外两个图标设为 inactive
    sessionTabBtn->setIcon(QIcon(":/resource/image/session_active.png"));
    friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));
    applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));
    //3.在主窗口中间部分,加载出会话列表数据
    this->loadSessionList();
}

void MainWidget::switchTabToFriend()
{
    //1.记录到切换到了哪个标签页
    activetab = FRIEND_LIST;
    //2.调整图标情况，把好友按钮图标设为inactive, 另外两个图标设为inactive
    sessionTabBtn->setIcon(QIcon(":/resource/image/session_inactive.png"));
    friendTabBtn->setIcon(QIcon(":/resource/image/friend_active.png"));
    applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));
    //3.在主窗口部分加载出好友列表数据;
    this->loadFriendList();
}

void MainWidget::switchTabToApply()
{
    //1.记录切换到哪个标签页
    activetab = APPLY_LIST;
    //2.调整图标情况,把好友申请图标设为active, 另外两个图标设为inactive;
    sessionTabBtn->setIcon(QIcon(":/resource/image/session_inactive.png"));
    friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));
    applyTabBtn->setIcon(QIcon(":/resource/image/apply_active.png"));
    //3.在主窗口加载出好友申请列表数据
    this->loadApplyList();
}

//加载会话列表
void MainWidget::loadSessionList()
{
    //先判断会话列表数据是否在本地 (DataCenter)中存在, 如果本地存在,直接构造界面内容
    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getChatSessionList() != nullptr)
    {
        // 从内存加载数据
        updateChatSessionList();
    }
    else
    {
        // 从网络加载数据
        connect(dataCenter, &DataCenter::getChatSessionListDone, this, &MainWidget::updateChatSessionList, Qt::UniqueConnection);
        dataCenter->getChatSessionListAsync();
    }
}

//加载好友列表
void MainWidget::loadFriendList()
{
    // 好友列表数据是在 DataCenter 中存储的
    // 首先需要判定 DataCenter 中是否有数据, 如果有数据,直接加载本地数据,
    //如果没有数据,从服务器获取
    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getFriendList() != nullptr)
    {
        //  从内存这个列表加载数据
        updateFriendList();
    }
    else
    {
        // 通过网络加载数据
        // 避免重复绑定信号槽
        connect(dataCenter, &DataCenter::getFriendListDone, this, &MainWidget::updateFriendList, Qt::UniqueConnection);
        dataCenter->getFriendListAnsync();
    }
}

//加载好友申请列表
void MainWidget::loadApplyList()
{
    // 好友申请列表 在DataCenter 中存储的
    //首先判定 DataCenter 本地是否有数据, 如果有直接加载到界面上
    //如果没有则需要从服务器中获取

    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getApplyList() != nullptr)
    {
        //本地有数据,直接加载
        LOG() << "本地有数据";
        updateApplyList();
    }
    else
    {
        LOG() << " 从网络获取";
        connect(dataCenter, &DataCenter::getApplyListDone,this, &MainWidget::updateApplyList, Qt::UniqueConnection);
        //本地没有数据,通过网络加载
        LOG() << " 从网络加载数据";
        dataCenter->getApplyListAsync();

    }
}

void MainWidget::updateFriendList()
{
    if (activetab != FRIEND_LIST)
    {
        //当前的标签页不是好友列表, 就不渲染任何数据到界面上
        return;
    }
    DataCenter* dataCenter = DataCenter::getInstance();
    QList<UserInfo>* friendList = dataCenter->getFriendList();


    // 清空之前界面的数据.
    sessionFriendArea->clear();

    //遍历好友列表, 添加到界面上
    for (const auto& f : *friendList)
    {
        sessionFriendArea->addItem(FriendItemType, f.userId, f.avatar, f.nickname, f.description);
    }
}

void MainWidget::updateChatSessionList()
{
    if (activetab != SESSION_LIST)
    {
        //当前标签页不是会话列表, 不渲染任何数据到界面上
        return;
    }
    DataCenter* dataCenter = DataCenter::getInstance();
    LOG() << " 获取实列";
    QList<ChatSessionInfo>* chatSessionList = dataCenter->getChatSessionList();

    sessionFriendArea->clear();

    for (const auto& c : *chatSessionList)
    {

        //需要对消息类型做判定,文本消息直接显示文本消息的内容，图片消息显示图片,文件消息显示文件,语言消息显示语音
       if (c.lastMessage.messageType == TEXT_TYPE)
        {

            sessionFriendArea->addItem(SessionItemType, c.chatSessionId,
                                      c.avatar, c.chatSessionName, c.lastMessage.content);


       }
       else if (c.lastMessage.messageType == IMAGE_TYPE)
       {
           sessionFriendArea->addItem(SessionItemType, c.chatSessionId, c.avatar, c.chatSessionName,"[图片]");
       }
       else if(c.lastMessage.messageType == FILE_TYPE)
       {
           sessionFriendArea->addItem(SessionItemType, c.chatSessionId, c.avatar, c.chatSessionName,"[图片]");
       }
       else if(c.lastMessage.messageType == SPEECH_TYPE)
       {
          sessionFriendArea->addItem(SessionItemType, c.chatSessionId, c.avatar, c.chatSessionName,"[语言]");
       }
       else
       {
           LOG() << "错误的消息类型! messageType=" << c.lastMessage.messageType;
       }
    }

}

void MainWidget::updateApplyList()
{
   if (activetab != APPLY_LIST)
    {
       // 当前标签页不是 "好友申请列表", 界面上不做任何渲染
       return;
   }
   DataCenter* dataCenter = DataCenter::getInstance();
   QList<UserInfo>* applyList = dataCenter->getApplyList();

   sessionFriendArea->clear();
   for (const auto& u : *applyList)
   {
       // 此处直接添加UserInfo对象添加到界面上即可, 不涉及到 PB 和 自己结构之间的转换.
       //此处 UserInfo 的 description 不需要填写进来, 好友申请列表中,不显示用户签名的 (这个位置被换成的两个按钮)
       sessionFriendArea->addItem(ApplyItemType, u.userId, u.avatar, u.nickname,"");

   }

}

// 程序启动后,用户点击某个会话的时候, 就需要加载消息列表,在消息区显示
void MainWidget::loadRecentMessage(const QString &chatSessionId)
{
    // 也是先判定本地内存中是否已经有对应的消息列表数据
    // 有的话直接从本地加载没有就从网络获取
    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getRecentMessageList(chatSessionId) != nullptr)
    {
        // 拿着本地数据更新界面
        updateRecentMessage(chatSessionId);

    }
    else
    {
        connect(dataCenter, &DataCenter::getRecentMessageListDone, this, &MainWidget::updateRecentMessage, Qt::UniqueConnection);
        // 本地没有数据,从网络加载
        dataCenter->getRecentMessageListAsync(chatSessionId, true);

    }
}

void MainWidget::updateRecentMessage(const QString &chatSessionId)
{
    //1 拿到该会话的最近消息列表
    DataCenter* dataCenter = DataCenter::getInstance();
    auto* recentMessageList  = dataCenter->getRecentMessageList(chatSessionId);

    //2 清空原有界面上显示的消息列表
    messageShowArea->clear();

    //3 根据当前拿到的消息列表,显示到界面上
    // 此处把消息显示到界面上,可使用头插和尾插
    // 这里打算使用头插,用户首先看到的,应该是"最近的" 消息,也就是末尾的消息

    for (int i = recentMessageList->size() - 1; i >=0; --i)
    {
        const Message& message  = recentMessageList->at(i);
        //isLeft 决定的消息显示在左侧还是右侧,别人的消息显示在左侧,自己的消息显示在右侧
        //就可以通过消息发送者的 userid,和用户自身的userid进行判定
        //如果相同就说明是自己的消息 isLeft = false
        //如果不同,说明是别人的消息 isLeft = true;
        bool isLeft = message.sender.userId != dataCenter->getMyself()->userId;
        messageShowArea->addFrontMessage(isLeft, message);
    }

    // 4 设置会话标题
    ChatSessionInfo* chatSessionInfo = dataCenter->findChatSessionById(chatSessionId);
    if (chatSessionInfo != nullptr)
    {
        //把会话名称显示到界面上
        sessionTitleLabel->setText(chatSessionInfo->chatSessionName);
    }

    // 5 保存当前选中的会话是哪个
    dataCenter->setCurrentChatsessionId(chatSessionId);

    //Qt 中把某个元素,添加到布局管理器中,还需要一个在界面显示的过程 这个过程是异步的,添加完毕后Qt还需要一点时间完成界面绘制
    // 添加元素到布局管理器之后,立即调整滚动条位置,大概率得到的是一个错误位置,里面的元素还没真正绘制完得到的滚动条.

    // 6 自动把滚动条,滚动到末尾
    messageShowArea->scrollToEnd();

}

void MainWidget::switchSession(const QString &userId)
{
    // 1 在会话列表中,先找到对应的会话元素
    DataCenter * dataCenter = DataCenter::getInstance();
    ChatSessionInfo* chatSessionInfo = dataCenter->findChatSessionByUserId(userId);
    if (chatSessionInfo == nullptr)
    {
        // 正常来说,每个好友 都有一个对应的会话(哪怕从来没说过话)
        // 添加好友的时候,就创建出来的会话
        LOG() << "[严重错误]当前选中的好友,对应的会话不存在!";
        return;
    }

    // 2 把选址的会话置顶、把这个会话信息放到整个会话列表的第一个位置
    // 后续在界面显示的时候就是,按照列表的顺序从前往后显示的
    dataCenter->topChatSessionInfo(*chatSessionInfo);

    // 3 切换到会话列表标签页
    switchTabToSession();

    // 4 加载会话对应的历史消息, 刚刚做的一个置顶操作, 被选中的好友对应的会话,在会话的列表的最前面,也就是0号下表
    sessionFriendArea->clickItem(0);



}

MessageShowArea *MainWidget::getMessageShowArea()
{
    return messageShowArea;
}

